﻿using System;

namespace CopyEventCode
{
    public delegate void DownloadStartHander(object obj, EventArgsDownloadStart args);
    public delegate void DownloadingHander(object obj, EventArgsDownloading args);
    public delegate void DownloadEndHander(object obj, EventArgsDownloadEnd args);
    
    public class EventArgsDownloadStart
    {
        private string url;
        public string Url { get => url; set => url = value; }

        public EventArgsDownloadStart(string url)
        {
            this.url = url;
        }
    }

    public class EventArgsDownloading
    {
        private string url;
        public string Url { get => url; set => url = value; }
        public double Percent { get => _percent; set => _percent = value; }

        private double _percent;
       
        public EventArgsDownloading(string url, double percent)
        {
            this.url = url;
            this._percent = percent;
        }
    }

    public class EventArgsDownloadEnd
    {
        public string Url { get { return _url; } set { _url = value; } }
        private string _url;

        public long ByteCount { get { return _byteCount; } set { _byteCount = value; } }
        private long _byteCount;

        public EventArgsDownloadEnd(string url, long size) { this._url = url; this._byteCount = size; }
    }

    public class Crawler
    {
        //声明事件
        public event DownloadStartHander DownloadStart; //public event 委托名 事件名
        public event DownloadingHander Downloading;
        public event DownloadEndHander DownloadEnd;

        Random rnd = new Random();
        private string site;
        public string Site { get => site; set => site = value; }
        public string Name { get { return name; } set { name = value; } }
        private string name;

        public Crawler(string name, string site)
        {
            this.site = site;
            this.name = name;
        }

        public void Craw()
        {
            while (true)
            {
                string url = getNextUrl();
                if (url == null) break;
                long size = getSizeOfUrl(url);
                
                //开始下载
                if (DownloadStart != null)
                    DownloadStart(this, new EventArgsDownloadStart(url));

                //下载中， 每次下载1024个字节
                for (int i = 0; i < size + 1024; i += 1024){
                    System.Threading.Thread.Sleep(100);
                    double percent = (int)(i * 100.0 / size);
                    if (percent > 100)
                        percent = 100;
                    if (Downloading != null)
                        Downloading(this, new EventArgsDownloading(url, percent));

                }

                if (DownloadEnd != null)
                {
                    DownloadEnd(this, new EventArgsDownloadEnd(url, size));
                }
            }
        }


        private long getSizeOfUrl(string url)
        {
            return rnd.Next(2000 * url.Length);
        }

        private string getNextUrl()
        {
            int a = rnd.Next(10);

            if (a == 0) return null;

            return site + "/Page" + a + ".html";
        }
    }

    class TestEvent {
        static void Main()
        {

            Crawler crawler = new Crawler("Crawer101", "https://www.pku.edu.cn");

            crawler.DownloadStart += new DownloadStartHander(ShowStart); //注册事件
            crawler.DownloadEnd += new DownloadEndHander(ShowEnd);
            crawler.Downloading += new DownloadingHander(ShowPercent);//DownloadingHandler

            crawler.Craw();
            Console.ReadKey();
        }

        static void ShowStart(object sender, EventArgsDownloadStart e)
        {
            Console.WriteLine((sender as Crawler).Name + "开始下载" + e.Url);
        }

        static void ShowEnd(object sender, EventArgsDownloadEnd e)
        {
            Console.WriteLine("\n\r下载" + e.Url + "结束,其下载" + e.ByteCount + "字节");
        }

        static void ShowPercent(object sender, EventArgsDownloading e)
        {
            Console.Write("\r下载" + e.Url + "......." + e.Percent + "%"); //只回车，不换行，覆盖上次输入
        }
    }
}